home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacWorld 1999 July
/
Macworld (1999-07).dmg
/
Shareware World
/
Info
/
For Developers
/
Mops 3.4.sea
/
Mops source
/
PPC source
/
bug fix.doc
< prev
next >
Wrap
Text File
|
1998-12-09
|
11KB
|
409 lines
\ Initialization of system objects.
syscall AEInstallEventHandler
syscall InstallExceptionHandler
: -MODELESS \ Sets normal event handling - no modeless dialogs
xts{ null-evt mouse-evt null-evt key-evt
null-evt key-evt upd-evt disk-evt
actv-evt null-evt null-evt null-evt
null-evt null-evt null-evt OS-evt
null-evt null-evt null-evt null-evt
null-evt null-evt null-evt HL-evt }
put: fEvent ;
' null-evt fill: fevent \ using -modeless during compilation causes
\ strange scrolling effects in fWind
\ ==================== :PPC_PROC =====================
:ppc_code :entry_code
rOSSP -256 rOSSP stwu,
RTOC 20 rOSSP stw,
r13 100 rOSSP stw,
r14 104 rOSSP stw,
r15 108 rOSSP stw,
r16 112 rOSSP stw,
r17 116 rOSSP stw,
r18 120 rOSSP stw,
r19 124 rOSSP stw,
r13 104 rTOC lwz,
r14 108 rTOC lwz,
\ r15 112 rTOC lwz,
\ r16 116 rTOC lwz,
r17 120 rTOC lwz,
r17 r17 -1024 addi,
r18 124 rTOC lwz,
r18 r18 -4096 addi,
r19 128 rTOC lwz,
;ppc_code
:ppc_code ;entry_code
r13 100 rOSSP lwz,
r14 104 rOSSP lwz,
r15 108 rOSSP lwz,
r16 112 rOSSP lwz,
r17 116 rOSSP lwz,
r18 120 rOSSP lwz,
r19 124 rOSSP lwz,
rOSSP 0 rOSSP lwz, \ take down frame
blr,
;ppc_code
(* :PPC_PROC begins a definition that is to be used as a callback.
Note that we make no provision to call one of these directly from
Mops code -- there's really no reason why anyone would want to.
We use a handler code of BE04, and add some extra info after
the header and before the code starts. This is the logical place
to put this info, although it means that we can't use "postpone :".
See the comments in the code below for the nuts and bolts.
At ;ppc_proc time, we add code at the beginning and the end
to save the regs we're going to change, set up the Mops
regs, then restore everything at the end. This is the same
as what we have to do with :ENTRY words (entry points for
a shared library).
*)
: :PPC_PROC ( procInfo -- 306 )
CDP -> const_data_start
ppc_header
$ BE040000 code, \ handler code for :PPC_proc defns,
\ and alignment
align4 \ align in data area
CDP \ save CDP for reloc!
0 code, \ in code area, space for reloc ptr
swap code, \ and then comes the procInfo
0 code, \ 2 bytes padding, 2 initial flag bytes
DP swap reloc! \ store reloc pointer to data area
12 reserve \ in data area, leave room for:
\ 4 bytes: pointer to routine descriptor
\ 8 bytes: transfer vector
\ We set these up at fix_procs below, at objinit time.
false -> method?
false -> noname?
0 >size: control_stk 0 >size: control_flags
false ppc_entry \ handle ppc proc entry
false -> leaf? \ so our parms get handled consistently
postpone hide \ new word is hidden until defn end
1 -> gpr_rtn_cnt \ :ppc_procs always return just one result in r3
-1 -> fpr_rtn_cnt \ this may need revising $$$$$$$$
true -> entry?
drop 306 \ use different security marker from colon
; immediate
: ;ppc_proc { \ x -- }
306 ?defn
curr-def 2- (;)
-4 ++> CDP \ delete the blr
['] ;entry_code 2+ CDP 36 aligned_move
36 ++> CDP
['] :entry_code 2+
curr-def
64 aligned_move
; immediate
konst uppAEEventHandlerProcInfo
:ppc_proc openAppHandler { x y z -- noErr } 0 ;ppc_proc
konst uppAEEventHandlerProcInfo
:ppc_proc openDocHandler { x y z -- noErr } 0 ;ppc_proc
konst uppAEEventHandlerProcInfo
:ppc_proc printDocHandler { x y z -- noErr } 0 ;ppc_proc
konst uppAEEventHandlerProcInfo
:ppc_proc quitAppHandler { x y z -- noErr } 0 ;ppc_proc
: (fix_proc) { xt dummy \ addr procInfo ^flags -- }
xt 2- w@ $ BE04 <> ?EXIT \ out if this isn't a :PPC_proc
xt 6 + @ -> procInfo \ pick up the procInfo for passing to
\ NewRoutineDescriptor
xt 2+ @abs -> addr \ now we look at data area info
xt 12 + -> ^flags
^flags c@ $ 10 and \ fp flags?
IF 6 ELSE 2 THEN
^flags + \ defn code starts here
addr 4+ ! \ set up the transition vector
RTOC addr 8 + !
\ now we call NewRoutineDescriptor - this returns a pointer to a
\ new descriptor - this pointer is a Universal ProcPtr (UPP).
\ We store this at addr.
addr 4+ \ tv addr
procInfo konst kPowerPCISA NewRoutineDescriptor
addr !
;
: fix_procs
['] (fix_proc) 0 trav ;
: install_AE_handler ( aevt-type event-type xt -- )
\ 2+ @abs @ \ get the UPP from the :proc info
0 \ handlerRefCon = 0
0 \ isSysHandler = false
AEInstallEventHandler ?startUpError
;
: install_reqd_appleEvents
'type aevt 'type oapp
['] openAppHandler \ AE handler addr
install_AE_handler
'type aevt 'type odoc
['] openDocHandler
install_AE_handler
'type aevt 'type pdoc
['] PrintDocHandler
install_AE_handler
'type aevt 'type quit
['] QuitAppHandler
install_AE_handler
;
\ =================== EXCEPTIONS ===================
(*
We have to resort to assembly for our exception handler, since
when it's called none or our registers are set up! We recover
them from the register save area in the exception info (see the
description of this in IM). Each reg is saved in 8 bytes, so
everything will be compatible on future 64-bit PPCs. (When
that happens, we'll have to revise this code. I think it will
be a while yet.)
On entry, r3 -> the exception info.
Note from Apple:
An ExceptionHandler is NOT a UniversalProcPtr.
It must be a native function pointer with NO routine descriptor.
*)
variable temp
:ppc_code myExceptionHandler
r5 0 r3 lwz, \ r5 = exception type - will be TOS
r12 8 r3 lwz, \ r12 -> register info
r12 r12 4 addi, \ look at lo 32 bits of regs
r1 8 r12 lwz, \ restore r1
r2 16 r12 lwz, \ r2
r3 3 8 * r12 lwz, \ we'll get r3 and r4 since that
r4 4 8 * r12 lwz, \ might help in the error dump
r13 13 8 * r12 lwz,
r14 14 8 * r12 lwz,
r15 15 8 * r12 lwz,
r16 16 8 * r12 lwz,
r17 17 8 * r12 lwz,
r18 18 8 * r12 lwz,
r19 19 8 * r12 lwz,
r20 20 8 * r12 lwz,
r21 21 8 * r12 lwz,
(* r22 22 8 * r12 lwz, \ not much point in bothering
r23 23 8 * r12 lwz, \ with these
r24 24 8 * r12 lwz,
r25 25 8 * r12 lwz,
r26 26 8 * r12 lwz,
r27 27 8 * r12 lwz,
r28 28 8 * r12 lwz,
r29 29 8 * r12 lwz,
r30 30 8 * r12 lwz,
r31 31 8 * r12 lwz,
*)
r0 ' (excep) 2+ dicaddr, \ we set (excep) up with 3 parms
r0 mtctr,
bctr,
;ppc_code
: install_my_exception_handler
['] myExceptionHandler 2+ temp !
temp InstallExceptionHandler drop
;
: fix_segments { \ ^ST len segStart #chopped curr_code curr_data -- }
instld? 0EXIT
segTable -> ^ST
code_start -> curr_code
code_start 56 + @ -> #chopped
curr_code #chopped - segTable 4+ ! \ seg 8 base addr (main dic code)
code_start 4+ @ dup ++> curr_code
#chopped + segTable ! \ seg 8 length
data_start -> curr_data
code_start 60 + @ -> #chopped
curr_data #chopped - segTable 12 + ! \ seg 9 base addr (main dic data)
code_start 8 + @ dup ++> curr_data
#chopped + segTable 8 + ! \ seg 9 length
max_segs 2
DO i 8 * segTable + -> ^ST
^ST c@ 1 and
IF \ this one is installed
^ST @ $ 00ffffff and #align4 -> len
i 1 and
IF \ it's data
curr_data ^ST 4+ !
len ++> curr_data
ELSE \ it's code
curr_code ^ST 4+ !
len ++> curr_code
THEN
THEN
LOOP
;
: chk_thread { thread# \ thread_addr prev_lfa lfa -- }
thread# dummy_len c! \ fake a "length byte" for THREAD
dummy_len thread -> thread_addr \ addr of thread start in CONTEXT
thread_addr displace -> lfa \ addr of first link field in thread,
\ in CONTEXT
lfa -> prev_lfa
BEGIN lfa
WHILE lfa -> prev_lfa
lfa displace -> lfa
REPEAT
;
: chkdic
#threads FOR i chk_thread NEXT
;
\ Any special run-time initialization can be done conveniently by adding
\ the appropriate words to the x-col INIT_ACTIONS. These words will be
\ executed on startup via EXTRA_INITS, right after the rest of the
\ initialization stuff has been done.
8 x-col INIT_ACTIONS
: EXTRA_INITS
size: init_actions 0 ?DO i exec: init_actions LOOP
;
: SYSINIT \ our final initialization word. Called regardless ofwhether
\ we're in the development environment or an installed app.
init2
fix_segments
fix_procs
install_reqd_appleEvents
install_my_exception_handler
0 -> actW
resize_fWind
$ F5EF setMask: fEvent \ mask out key up
-modeless key! +curs
extra_inits \ do any extra initialization
;
(*
PAUSE should be called at strategic intervals in all applications,
unless Key is being called frequently (see note 1 below). Pause
normally calls next: fEvent which allows a task switch to be done
under MultiFinder, and which also handles any pending events for this
task, such as window updates. Remember to disable any menus etc. that
you don't want to execute in this situation! Unexpected re-entrancy
is a good way to bomb!
NOTE THE FOLLOWING POINTS:
1. KEY also calls next: fEvent. So if we're waiting on keys,
we shouldn't call Pause, especially as Pause will gobble any keys
typed!
2. next: fEvent calls WaitNextEvent. If we don't want to be
suspended until the next event for us, we need to set SleepTicks to
a suitably low number. PAUSE by default sets SleepTicks to zero
temporarily. Change this if necessary.
3. If multitasking is installed, PAUSE may be redirected (but not
necessarily) so that it just calls NEXT_TASK to do a task switch.
This will happen if we have a foreground task calling next: fEvent
repeatedly, while we do all the real work in the background.
This way we can keep executing during window drags and menu selections.
4. Dereferenced pointers may become invalid across a PAUSE. Be careful.
*)
: (PAUSE)
savingDic? ?EXIT \ If called during a dic save, mustn't process
\ events since modules are purged
sleepticks 0 -> sleepticks
getMask: fEvent $ FFC7 setMask: fEvent \ all except key events
next: fEvent \ IF 2drop THEN \ 30Apr94 DBH next: no longer returns stack items
setMask: fEvent -> sleepticks ;
\ CL3 is the next cleanup word - it cleans up all object stuff on abort,
\ as well as whatever we were doing before (see CL2 in file Files, and CL1
\ in file Class).
: CL3
( key! ) 0 HiliteMenu arrowcurs
cl2 ;
: (SF)
alive: fWind IF setContRect: fWind set: fWind select: fWind THEN
initfont ;
' sysinit -> objinit
' (pause) -> pause
' (sf) -> setFwind
' cl3 -> abortvec
:f RUN
cr ." This is the stage 3 nucleus." cr
QUIT
;f
\ ========= Some ppc_procs we need which are used in modules =========
\ TEScroller
nilP value ClickedScroller
konst uppTEClickLoopProcInfo
:ppc_proc DRAGPROC
autoScroll: [ clickedScroller ]
1 \ We have to return a Pascal boolean TRUE!
;ppc_proc